package com.yunsc.store.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import com.yunsc.common.base.YunscStoreUser;
import com.yunsc.common.base.YunscUser;
import com.yunsc.common.exception.YunscException;
import com.yunsc.common.utils.RedisUtils;
import com.yunsc.store.entity.YunscUserEntity;
import com.yunsc.store.service.YunscLoginService;
import com.yunsc.store.service.YunscStoreSettingService;
import com.yunsc.store.service.YunscUserService;
import com.yunsc.store.vo.SMSNoticeVO;
import com.yunsc.system.dto.AuthParamsDto;
import com.yunsc.system.dto.ShopLoginDTO;
import com.yunsc.system.dto.SmsCaptchaDTO;
import com.yunsc.system.entity.YunscStoreUserEntity;
import com.yunsc.system.service.YunscStoreUserService;
import com.yunsc.system.utils.SMSUtils;
import com.yunsc.system.vo.PicVerifyCodeVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.awt.*;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;

/**
 * @version: 1.0
 * @Author: adan
 * @description:
 * @date: 2024-04-11 13:22
 */
@Slf4j
@Service
public class YunscLoginServiceImpl implements YunscLoginService {

    @Resource
    private YunscStoreUserService storeUserService;
    @Resource
    private YunscUserService userService;
    @Resource
    private RedisUtils redisUtils;
    @Resource
    private YunscStoreSettingService storeSettingService;

    /**
     * 登录
     *
     * @param authParam 登录参数
     * @return 登录结果
     */
    @Override
    public Map<String, Object> storeLogin(AuthParamsDto authParam) {
        String username = authParam.getUsername();
        String passwordForm = authParam.getPassword();
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(passwordForm)) {
            throw new YunscException("请输入用户名和密码");
        }
        // 校验用户是否存在
        YunscStoreUserEntity user = storeUserService.getOne(new QueryWrapper<YunscStoreUserEntity>().eq("user_name", username));
        if (user == null) {
            throw new YunscException("用户名不存在");
        }

        // 校验密码
        String passwordDb = user.getPassword();
        String hashpw = BCrypt.hashpw(passwordForm, BCrypt.gensalt());
        boolean matches = BCrypt.checkpw(passwordForm, passwordDb);
        if (!matches) {
            throw new YunscException("用户名或密码错误");
        }
        // 获取用户之前的token
        String oldToken = StpUtil.getTokenValueByLoginId(user.getStoreId());
        // 如果之前的token存在，则先退出登录
        if (StringUtils.isNotBlank(oldToken)) {
            StpUtil.logout(user.getStoreId());
        }
        // 认证通过，就使用userid生成一个token
        StpUtil.login(user.getStoreId());
        String tokenValue = StpUtil.getTokenValue();
        log.info("登录成功，tokenValue={}， username={}", tokenValue, username);
        // 将用户信息存入Session
        YunscStoreUser storeUser = new YunscStoreUser();
        BeanUtils.copyProperties(user, storeUser);
        StpUtil.getSession().set("store_user", storeUser);

        Map<String, Object> map = new LinkedHashMap<>();
        map.put("token", tokenValue);
        map.put("userId", user.getStoreId());
        return map;
    }

    @Override
    public PicVerifyCodeVO generatePicCheckCode() {
        // 三个参数分别为宽、高、位数
        SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 4);
        // 设置字体
        specCaptcha.setFont(new Font("Verdana", Font.PLAIN, 32));  // 有默认字体，可以不用设置
        // 设置类型，纯数字、纯字母、字母数字混合
        specCaptcha.setCharType(Captcha.TYPE_ONLY_NUMBER);
        String text = specCaptcha.text();
        String base64 = specCaptcha.toBase64();
        // 加密验证码值ase加密算法
        // String codeValue = yunscEncrypt(text);
        String decrypt = BCrypt.hashpw(text, BCrypt.gensalt());

        // 构建返回结果
        PicVerifyCodeVO picVerifyCodeVO = new PicVerifyCodeVO();
        picVerifyCodeVO.setKey(decrypt);
        picVerifyCodeVO.setBase64(base64);
        String md5Hex = DigestUtils.md5Hex(text);
        picVerifyCodeVO.setMd5(md5Hex);

        return picVerifyCodeVO;
    }

    @Override
    public void sendSmsCaptcha(SmsCaptchaDTO smsCaptchaDTO, Integer storeId) {
        // 校验验证码是否正确
        String codeValue = smsCaptchaDTO.getForm().getCaptchaCode();
        String codeKey = smsCaptchaDTO.getForm().getCaptchaKey();

        // 解密算法
        // String decrypt = yunscDecrypt(codeKey);

        boolean matches = BCrypt.checkpw(codeValue, codeKey);
        if (!matches) {
            throw new YunscException("很抱歉，图形验证码不正确");
        }
        // if (!codeValue.equals(decrypt)) {
        //     throw new YunscException("很抱歉，图形验证码不正确");
        // }
        // 发送短信验证码
        // 生成6位随机验证码
        Random randObj = new Random();
        String code = Integer.toString(100000 + randObj.nextInt(900000));
        // 发送短信验证码

        SMSNoticeVO smsNoticeVO = storeSettingService.querySMSSettingVO(storeId);
        String defaultEngine = smsNoticeVO.getDefaultEngine();
        String mobile = smsCaptchaDTO.getForm().getMobile();
        if (!smsNoticeVO.getScene().getCaptcha().isEnable()){
            log.info("短信验证码已发送，{}", code);
            // 保存验证码到redis
            redisUtils.set(mobile, code, 60);
            throw new YunscException("您的验证码为：" + code);
        }
        if ("aliyun".equals(defaultEngine)){
            // 阿里云短信发送
            SMSNoticeVO.SMSAliyun aliyun = smsNoticeVO.getEngine().getAliyun();
            String accessKeyId = aliyun.getAccessKeyId();
            String accessSecret = aliyun.getAccessKeySecret();
            String signName = aliyun.getSign();
            String templateCode = smsNoticeVO.getScene().getCaptcha().getTemplateCode();
            SMSUtils.sendMessage(signName, templateCode, mobile, code, accessKeyId, accessSecret);
        }else if ("qcloud".equals(defaultEngine)){
            // 腾讯云短信发送
            SMSNoticeVO.SMSQcloud qcloud = smsNoticeVO.getEngine().getQcloud();
            String appId = qcloud.getSdkAppID();
            String accessKeyId = qcloud.getAccessKeyId();
            String accessKeySecret = qcloud.getAccessKeySecret();
            String signName = qcloud.getSign();
            String templateCode = smsNoticeVO.getScene().getCaptcha().getTemplateCode();
            String[] templateParam = {code};
            String[] phoneNumbers = {"+86"+mobile};
            SMSUtils.sendQcloudMessage(accessKeyId, accessKeySecret, appId, signName, templateCode, templateParam, phoneNumbers);
        }else{
            // 未配置短信发送引擎
            log.error("未配置短信发送引擎");
        }

        // 保存验证码到redis
        redisUtils.set(mobile, code, 60);
    }


    @Override
    public Map<String, Object> shopLogin(ShopLoginDTO authParam, String platform, Integer storeId) {
        // 校验参数
        String smsCode = (String) redisUtils.get(authParam.getForm().getMobile());
        if (StringUtils.isEmpty(smsCode) || !smsCode.equals(authParam.getForm().getSmsCode())) {
            throw new YunscException("验证码错误");
        }

        // 校验用户是否存在
        YunscUserEntity user = userService.getOne(new QueryWrapper<YunscUserEntity>()
                .eq("mobile", authParam.getForm().getMobile()));
        if (user == null) {
            // 用户不存在，则注册用户
            user = new YunscUserEntity();
            user.setMobile(authParam.getForm().getMobile());
            // 截取手机号后四位作为昵称
            String nickName = authParam.getForm().getMobile().substring(authParam.getForm().getMobile().length() - 4);

            user.setNickName("用户_"+nickName);
            user.setPlatform(platform);
            user.setLastLoginTime((int) (System.currentTimeMillis()/1000));
            user.setStoreId(storeId);
            // 保存用户信息
            userService.save(user);
        }

        // 获取用户之前的token
        String oldToken = StpUtil.getTokenValueByLoginId(user.getUserId());
        // 如果之前的token存在，则先退出登录
        if (StringUtils.isNotBlank(oldToken)) {
            StpUtil.logout(user.getStoreId());
        }
        // 认证通过，就使用userid生成一个token
        StpUtil.login(user.getUserId());
        String tokenValue = StpUtil.getTokenValue();
        log.info("登录成功，tokenValue={}， username={}", tokenValue, user.getNickName());
        // 将用户信息存入Session
        YunscUser userEntity = new YunscUser();
        BeanUtils.copyProperties(user, userEntity);
        StpUtil.getSession().set("user", userEntity);

        Map<String, Object> map = new LinkedHashMap<>();
        map.put("token", tokenValue);
        map.put("userId", user.getUserId());
        return map;
    }


}
